package com.ruoyi.media.pay.wechatPayService;

import com.ruoyi.common.utils.StringUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class WexinPayService {

    // 统一下单API
    private static final String UNIFIED_ORDER_API = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    /**
     * 小程序id
     */
    @Value("${pay.wechatPay.appId}")
    private  String appId;
    /**
     * apiKey
     */
    @Value("${pay.wechatPay.apiKey}")
    private  String apiKey;
    /**
     * 商户id
     */
    @Value("${pay.wechatPay.mchId}")
    private  String mchId;

    /**
     * 统一下单
     *
     * @param body       商品描述
     * @param outTradeNo 订单号
     * @param totalFee   总金额（分）
     * @return
     * @throws Exception
     */
    public  Map<String, String> unifiedOrder(String body, String outTradeNo, int totalFee) throws Exception {
        Map<String, String> params = new HashMap<>();
        params.put("appid", appId);
        params.put("mch_id", mchId);
        params.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));
        params.put("body", body);
        params.put("out_trade_no", outTradeNo);
        params.put("total_fee", String.valueOf(totalFee));
//        params.put("spbill_create_ip", "127.0.0.1");
        params.put("notify_url", "http://toolssh.5gzvip.91tunnel.com/api/pay/callback");
        params.put("trade_type", "NATIVE");
        params.put("sign", generateSign(params, apiKey));
        String xml = mapToXml(params);
        String response = doPost(UNIFIED_ORDER_API, xml);
        Map<String, String> resultMap = xmlToMap(response);

        return resultMap;
    }

    /**
     * 生成签名
     *
     * @param params
     * @param apiKey
     * @return
     */
    public  String generateSign(Map<String, String> params, String apiKey) {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);

        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            String value = params.get(key);
            if (StringUtils.isNotBlank(value) && !"sign".equals(key) && !"key".equals(key)) {
                sb.append(key).append("=").append(value).append("&");
            }
        }
        sb.append("key=").append(apiKey);

        return DigestUtils.md5Hex(sb.toString()).toUpperCase();
    }

    /**
     * Map转XML
     *
     * @param params
     * @return
     * @throws Exception
     */
    public  String mapToXml(Map<String, String> params) throws Exception {
        Document document = DocumentHelper.createDocument();
        Element root = document.addElement("xml");
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            if (StringUtils.isNotBlank(value)) {
                root.addElement(key).addCDATA(value);
            }
        }
        return document.asXML();
    }

    /**
     * XML转Map
     *
     * @param xml
     * @return
     * @throws Exception
     */
    public Map<String, String> xmlToMap(String xml) throws Exception {
        Map<String, String> resultMap = new HashMap<>();
        Document document = DocumentHelper.parseText(xml);
        Element root = document.getRootElement();
        List<Element> elements = root.elements();
        for (Element element : elements) {
            resultMap.put(element.getName(), element.getTextTrim());
        }
        return resultMap;
    }

    /**
     * 发送POST请求
     *
     * @param url
     * @param data
     * @return
     * @throws Exception
     */
    public  String doPost(String url, String data) throws Exception {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new StringEntity(data, "UTF-8"));
        CloseableHttpResponse response = httpClient.execute(httpPost);
        HttpEntity entity = response.getEntity();
        String result = EntityUtils.toString(entity, "UTF-8");
        response.close();
        httpClient.close();
        return result;
    }

}
